﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;

namespace XNAFight.Scene.Core
{
    public abstract class Screen : DrawableGameComponent
    {
        #region CHAMPS

        private bool is_alive;
        private bool is_listening_inputs;
        protected bool complete;

        private int activation_delay;
        private int activation_countdown;

        // Champs necessaires aux fonctions WriteLine
        Vector2 pos_leftText;
        Vector2 pos_rightText;

        #endregion

        #region PROPRIETES

        public bool IsAlive
        {
            get { return is_alive; }
        }

        public bool IsListeningInputs
        {
            get { return is_listening_inputs; }
        }

        protected int ActivationDelay
        {
            get { return activation_delay; }
            set
            {
                activation_delay = value;
                activation_countdown = value;
            }
        }

        #endregion

        #region EVENTS

        public event EventHandler Added;
        public event EventHandler Removed;
        public event EventHandler Activated;
        public event EventHandler Disabled;

        public event EventHandler Adding;
        public event EventHandler Removing;
        public event EventHandler Activating;
        public event EventHandler Disabling;

        public virtual event EventHandler Cancelled;
        public virtual event EventHandler Cancelling;

        public virtual event EventHandler Completed;
        public virtual event EventHandler Completing;
        #endregion

        #region INITIALISATION

        public Screen()
            : base(CommonContent.CurrentGame)
        {
            is_alive = false;
            is_listening_inputs = false;
            complete = false;
            
            activation_delay = 0;
            activation_countdown = 0;

            pos_leftText = new Vector2();
            pos_rightText = new Vector2();
        }
        #endregion
        
        #region UPDATE / DRAW

        public override void Update(GameTime _game_time)
        {
            base.Update(_game_time);

            ResetWriter();

            if (activation_delay > activation_countdown)
                Activate();

            if (IsListeningInputs)
                HandleInputs();
        }

        #endregion
        
        #region AUTRES METHODES
        
        protected void WriteLine(string _text, SpriteFont _font, bool _right_aligned = false)
        {
            if (_right_aligned)
                WriteLineOnRight(_text, _font);
            else
                WriteLineOnLeft(_text, _font);
        }
        private void WriteLineOnLeft(string _text, SpriteFont _font)
        {
            CommonContent.SpriteBatch.DrawString(_font, _text, pos_leftText, Color.Black);
            pos_leftText.Y += _font.MeasureString(_text).Y + 3;
        }
        private void WriteLineOnRight(string _text, SpriteFont _font)
        {
            Vector2 pos_right_buffer = new Vector2();
            pos_right_buffer.Y = pos_rightText.Y;
            pos_right_buffer.X = pos_rightText.X - _font.MeasureString(_text).X;
            CommonContent.SpriteBatch.DrawString(_font, _text, pos_right_buffer, Color.Black);
            pos_rightText.Y += _font.MeasureString(_text).Y + 3;
        }
        private void ResetWriter()
        {
            pos_leftText.X = 10;
            pos_leftText.Y = 10;

            pos_rightText.X = 790;
            pos_rightText.Y = 10;
        }

        public virtual void Reset()
        {
            complete = false;
        }
        public virtual void Reset(object _sender, EventArgs _e)
        {
            this.Reset();
        }
        public abstract void HandleInputs();

        public virtual void Add()
        {
            if (is_alive)
                return;

            if (Adding != null)
                Adding(this, new EventArgs());

            CommonContent.CurrentGame.Components.Add(this);
            is_alive = true;

            if (Added != null)
                Added(this, new EventArgs());
        }
        public virtual void Add(object _sender, EventArgs _e)
        {
            this.Add();
        }
        
        protected virtual void Remove()
        {
            if (!is_alive)
                return;

            if (Removing != null)
                Removing(this, new EventArgs());

            CommonContent.CurrentGame.Components.Remove(this);
            is_alive = false;
            
            if (Removed != null)
                Removed(this, new EventArgs());
        }
        private void Remove(object _sender, EventArgs _e)
        {
            this.Remove();
        }

        public virtual void Activate()
        {
            if (is_listening_inputs)
                return;

            if (activation_countdown == 0)
            {
                activation_countdown = activation_delay;
            }
            else
            {
                activation_countdown--;
                return;
            }

            if (Activating != null)
                Activating(this, new EventArgs());

            is_listening_inputs = true;

            if (Activated != null)
                Activated(this, new EventArgs());
        }
        public virtual void Activate(object _sender, EventArgs _e)
        {
            this.Activate();
        }

        public virtual void Disable()
        {
            if (!is_listening_inputs)
                return;

            if (Disabling != null)
                Disabling(this, new EventArgs());

            is_listening_inputs = false;

            if (Disabled != null)
                Disabled(this, new EventArgs());
        }
        public virtual void Disable(object _sender, EventArgs _e)
        {
            this.Disable();
        }

        public virtual void Complete()
        {
            if (complete)
                return;

            OnCompleting();
            complete = true;
            this.Remove();
            OnComplete();
        }
        public virtual void Complete(object _sender, EventArgs _e)
        {
            Complete();
        }

        public virtual void Cancel()
        {
            this.Remove();
            OnCancel();
        }
        public virtual void Cancel(object _sender, EventArgs _e)
        {
            Cancel();
        }

        protected virtual void OnCancel()
        {
            if (Cancelled != null)
                Cancelled(this, new EventArgs());
        }
        protected virtual void OnCancel(object _sender, EventArgs _e)
        {
            OnCancel();
        }
        protected virtual void OnComplete()
        {
            if (Completed != null)
                Completed(this, new EventArgs());
        }
        protected virtual void OnComplete(object _sender, EventArgs _e)
        {
            OnComplete();
        }
        protected virtual void OnCompleting()
        {
            if (Completing != null)
                Completing(this, new EventArgs());
        }
        protected virtual void OnCompleting(object _sender, EventArgs _e)
        {
            OnCompleting();
        }
        protected virtual void OnCancelling()
        {
            if (Cancelling != null)
                Cancelling(this, new EventArgs());
        }
        protected virtual void OnCancelling(object _sender, EventArgs _e)
        {
            OnCancelling();
        }

        #endregion
    }
}
